﻿dynamic class D2.D2Chain{
	//var
	public var MC:MovieClip;
	public var MaxAngle:Number;
	public var MinAngle:Number;
	public var Child:D2Chain;
	public var Parent:D2Chain;
	public var Quan:Number;				//角度动作权重
	public var mcX:Number;				//内部记录的位置
	public var mcY:Number;				//内部记录的位置
	public var mcR:Number;				//内部记录的角度
	
	//private
	private var disChild:Number;
	private var disParent:Number;
	//event interface
	public static var say:Function;
	//
	
	public function D2Chain(bangdingMC:MovieClip){
		init();
		if(bangdingMC!=undefined){
			this.BangdingMovieClip(bangdingMC);
		}
	}
	private function init(){
		MaxAngle=Math.PI;
		MinAngle=-Math.PI;
		Quan=1;
		disChild=0;
		disParent=0;
	}
	//bind movieclip to class
	public function BangdingMovieClip(bangdingMC:MovieClip){
		MC=bangdingMC;
		MC._Chain=this;
		BangdingMCPs(bangdingMC);
	}
	
	private function BangdingMCPs(bangdingMC:MovieClip){
		this.mcR=bangdingMC._rotation*Math.PI/180;
		this.mcX=bangdingMC._x;
		this.mcY=bangdingMC._y;
	}
	//绑定子对象
	public function BangdingChild(childMC:MovieClip){
		if(childMC._Chain==undefined){
			childMC._Chain=new D2Chain(childMC);
		}
		childMC._Chain.Parent.Child=null;
		this.Child=childMC._Chain;
		this.Child.Parent=this;
		var offsetx:Number=MC._x-childMC._x;
		var offsety:Number=MC._y-childMC._y;
		var dis:Number=Math.pow((offsetx*offsetx+offsety*offsety),0.5);
		this.disChild=dis;
		this.Child.disParent=dis;
		Say("绑定Child ["+childMC+"]");
	}
	//绑定父对象
	public function BangdingParent(parentMC:MovieClip){
		if(parentMC._Chain==undefined){
			parentMC._Chain=new D2Chain(parentMC);
		}
		parentMC._Chain.Child.Parent=null;
		this.Parent=parentMC._Chain;
		parentMC._Chain.Child=this;
		Say("绑定parent ["+parentMC+"]");
	}
	
	public function Move(){
		MoveTo(this.MC._x,this.MC._y);
	}
	
	public function MoveTo(x:Number,y:Number){
		this.moveParentTo(x,y);
		var angle:Number=this.moveChildTo(x,y);
		this.moveSelfTo(x,y,angle);
	}
	public function moveParentTo(x:Number,y:Number){
		if(this.Parent!=null){
			this.Parent.moveWhenChildMove(x,y);
		}
	}
	public function moveSelfTo(x:Number,y:Number,angle:Number){
		this._moveTo(x,y);
		this._rotate(angle);
	}
	public function moveChildTo(x:Number,y:Number):Number{
		var angle:Number=this.mcR;
		if(this.Child!=null){
			angle=getRotation(this.Child.mcX,this.Child.mcY,this.mcX,this.mcY,this.Child.mcX,this.Child.mcY,x,y);
			var cx:Number=Math.cos(angle)*this.disChild;
			var cy:Number=Math.sin(angle)*this.disChild;
			cx+=x;
			cy+=y;
			this.Child.moveChildTo(cx,cy);
		}
		this.moveSelfTo(x,y,angle);
		return angle;
	}
	public function moveWhenChildMove(x:Number,y:Number){
		var angle:Number=this.mcR
		angle=getRotation(this.Child.mcX,this.Child.mcY,this.mcX,this.mcY,x,y,this.mcX,this.mcY);
		var cx:Number=Math.cos(angle)*this.disChild;
		var cy:Number=Math.sin(angle)*this.disChild;
		cx=x-cx;
		cy=y-cy;
		if(this.Parent!=null){
			this.Parent.moveWhenChildMove(cx,cy);
		}
		this._moveTo(cx,cy);
		this._rotate(angle);
	}
	private function _moveTo(x:Number,y:Number){
		this.MC._x=x;
		this.MC._y=y;
		this.mcX=x;
		this.mcY=y;
		Say("移动到("+x+","+y+")");
	}
	public function Rotate(angle:Number){
		var angleo:Number=this.mcR;
		angleo=getRotationLimite(angleo,angle*this.Quan);
		var cx:Number=Math.cos(angleo)*this.disChild;
		var cy:Number=Math.sin(angleo)*this.disChild;
		cx+=this.mcX;
		cy+=this.mcY;
		if(this.Child!=null){
			this.Child.moveChildTo(cx,cy);
		}
		this._rotate(angleo);
	}
	private function _rotate(angle:Number){
		this.MC._rotation=180*angle/Math.PI;
		this.mcR=angle;
		Say("转动("+angle+")度");
	}
	private function getRotation(x1:Number,y1:Number,cx1:Number,cy1:Number,x2:Number,y2:Number,cx2:Number,cy2:Number):Number{
		//trace(arguments)
		var angle:Number;
		angle=getAngleLessThenPI(x1,y1,cx1,cy1,x2,y2,cx2,cy2);
		angle=this.Quan*angle;
		var a1:Number=getAngle(x1,y1,cx1,cy1);
		return getRotationLimite(a1,angle);
	}
	private function getRotationLimite(angle:Number,offsetAngle:Number):Number{
		var a:Number=offsetAngle+angle;
		//if(a>this.MaxAngle) return this.MaxAngle;
		//if(a<this.MinAngle) return this.MinAngle;
		return a;
	}
	//求角度
	private function getAngle(x:Number,y:Number,cx:Number,cy:Number):Number{
		return Math.atan2((y-cy),(x-cx));
	}
	//求两角劣弧弧度
	private function getAngleLessThenPI(x1:Number,y1:Number,cx1:Number,cy1:Number,x2:Number,y2:Number,cx2:Number,cy2:Number):Number{
		var a1:Number=getAngle(x1,y1,cx1,cy1);
		var a2:Number=getAngle(x2,y2,cx2,cy2);
		var a:Number=a2-a1;
		if(a>=Math.PI){
			a=a-2*Math.PI;
		}
		if(a<=-Math.PI){
			a=2*Math.PI+a;
		}
		//trace("----- "+a1+";"+a2+";"+a);
		return a;
	}
	
	private function fixAngleTo2PI(angle:Number):Number{
		if(angle<0){
			angle=Math.PI+angle;
		}
		return angle;
	}
	////////////////////////////////////////////////////////////////
	public function Say(o:Object){
		D2.D2Chain.say(o);
	}
}